#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys
import os
import cv2
import numpy as np
import threading
import time
from PyQt5.QtWidgets import *
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import QTimer, pyqtSignal, QThread, Qt

# 添加上级目录到Python路径以导入MvImport模块
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from MvImport.MvCameraControl_class import *
from MvImport.MvErrorDefine_const import *
from MvImport.PixelType_header import *

class CameraThread(QThread):
    """相机采集线程"""
    image_ready = pyqtSignal(np.ndarray)
    
    def __init__(self, camera_index=0):
        super().__init__()
        self.camera_index = camera_index
        self.is_running = False
        self.cam = None
        
    def run(self):
        """运行相机采集"""
        try:
            # 枚举设备
            deviceList = MV_CC_DEVICE_INFO_LIST()
            tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
            
            ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
            if ret != 0 or deviceList.nDeviceNum == 0:
                print("没有找到设备!")
                return
                
            if self.camera_index >= deviceList.nDeviceNum:
                print(f"设备索引 {self.camera_index} 超出范围!")
                return
            
            # 创建相机实例
            self.cam = MvCamera()
            
            # 选择设备并创建句柄
            stDeviceList = cast(deviceList.pDeviceInfo[self.camera_index], POINTER(MV_CC_DEVICE_INFO)).contents
            
            ret = self.cam.MV_CC_CreateHandle(stDeviceList)
            if ret != 0:
                print(f"创建句柄失败! ret[0x{ret:08x}]")
                return
                
            # 打开设备
            ret = self.cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
            if ret != 0:
                print(f"打开设备失败! ret[0x{ret:08x}]")
                self.cam.MV_CC_DestroyHandle()
                return
            
            # 设置触发模式为off
            ret = self.cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
            if ret != 0:
                print(f"设置触发模式失败! ret[0x{ret:08x}]")
            
            # 开始取流
            ret = self.cam.MV_CC_StartGrabbing()
            if ret != 0:
                print(f"开始取流失败! ret[0x{ret:08x}]")
                self.cam.MV_CC_CloseDevice()
                self.cam.MV_CC_DestroyHandle()
                return
            
            print("相机开始采集...")
            self.is_running = True
            
            # 获取图像数据
            stOutFrame = MV_FRAME_OUT()
            memset(byref(stOutFrame), 0, sizeof(stOutFrame))
            
            while self.is_running:
                ret = self.cam.MV_CC_GetImageBuffer(stOutFrame, 1000)
                if ret == 0:
                    # 转换图像数据
                    data = (c_ubyte * stOutFrame.stFrameInfo.nFrameLen)()
                    cdll.msvcrt.memcpy(byref(data), stOutFrame.pBufAddr, stOutFrame.stFrameInfo.nFrameLen)
                    
                    # 根据像素格式转换图像
                    if stOutFrame.stFrameInfo.enPixelType == PixelType_Gvsp_Mono8:
                        # 单色图像
                        img_data = np.frombuffer(data, dtype=np.uint8)
                        img = img_data.reshape((stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth))
                        img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
                    elif stOutFrame.stFrameInfo.enPixelType == PixelType_Gvsp_RGB8_Packed:
                        # RGB图像
                        img_data = np.frombuffer(data, dtype=np.uint8)
                        img = img_data.reshape((stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth, 3))
                        img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
                    else:
                        # 其他格式，尝试转换为BGR
                        img_data = np.frombuffer(data, dtype=np.uint8)
                        img = img_data.reshape((stOutFrame.stFrameInfo.nHeight, stOutFrame.stFrameInfo.nWidth, -1))
                        if len(img.shape) == 2:
                            img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
                    
                    # 发送图像信号
                    self.image_ready.emit(img)
                    
                    # 释放图像缓存
                    self.cam.MV_CC_FreeImageBuffer(stOutFrame)
                else:
                    time.sleep(0.01)
                    
        except Exception as e:
            print(f"相机采集错误: {e}")
        finally:
            self.stop()
    
    def stop(self):
        """停止采集"""
        self.is_running = False
        if self.cam:
            try:
                self.cam.MV_CC_StopGrabbing()
                self.cam.MV_CC_CloseDevice()
                self.cam.MV_CC_DestroyHandle()
            except:
                pass

class SimpleCameraDemo(QMainWindow):
    """简单的相机演示窗口"""
    
    def __init__(self):
        super().__init__()
        self.camera_thread = None
        self.init_ui()
        
    def init_ui(self):
        """初始化界面"""
        self.setWindowTitle('海康威视USB3相机演示')
        self.setGeometry(100, 100, 800, 600)
        
        # 创建中央部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 创建布局
        layout = QVBoxLayout(central_widget)
        
        # 创建图像显示标签
        self.image_label = QLabel()
        self.image_label.setMinimumSize(640, 480)
        self.image_label.setStyleSheet("border: 2px solid gray;")
        self.image_label.setText("等待连接相机...")
        self.image_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.image_label)
        
        # 创建控制按钮
        button_layout = QHBoxLayout()
        
        self.start_button = QPushButton("开始采集")
        self.start_button.clicked.connect(self.start_camera)
        button_layout.addWidget(self.start_button)
        
        self.stop_button = QPushButton("停止采集")
        self.stop_button.clicked.connect(self.stop_camera)
        self.stop_button.setEnabled(False)
        button_layout.addWidget(self.stop_button)
        
        self.save_button = QPushButton("保存图像")
        self.save_button.clicked.connect(self.save_image)
        self.save_button.setEnabled(False)
        button_layout.addWidget(self.save_button)
        
        layout.addLayout(button_layout)
        
        # 状态标签
        self.status_label = QLabel("就绪")
        layout.addWidget(self.status_label)
        
        self.current_image = None
        
    def start_camera(self):
        """开始相机采集"""
        if self.camera_thread is None or not self.camera_thread.is_running:
            self.camera_thread = CameraThread(0)  # 使用第一个相机
            self.camera_thread.image_ready.connect(self.update_image)
            self.camera_thread.start()
            
            self.start_button.setEnabled(False)
            self.stop_button.setEnabled(True)
            self.save_button.setEnabled(True)
            self.status_label.setText("正在采集...")
    
    def stop_camera(self):
        """停止相机采集"""
        if self.camera_thread and self.camera_thread.is_running:
            self.camera_thread.stop()
            self.camera_thread.wait()
            
            self.start_button.setEnabled(True)
            self.stop_button.setEnabled(False)
            self.save_button.setEnabled(False)
            self.status_label.setText("已停止")
    
    def update_image(self, img):
        """更新图像显示"""
        print("DEBUG: img.shape =", img.shape)  # 调试输出

        # 确保图像是3通道的
        if len(img.shape) == 2:
            img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
        elif len(img.shape) == 3 and img.shape[2] == 1:
            img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

        self.current_image = img

        height, width, channel = img.shape
        max_width = self.image_label.width() - 10
        max_height = self.image_label.height() - 10

        if width > max_width or height > max_height:
            scale = min(max_width / width, max_height / height)
            new_width = int(width * scale)
            new_height = int(height * scale)
            img = cv2.resize(img, (new_width, new_height))
            height, width, channel = img.shape

        bytes_per_line = 3 * width
        q_img = QImage(img.data, width, height, bytes_per_line, QImage.Format_RGB888)
        pixmap = QPixmap.fromImage(q_img)
        self.image_label.setPixmap(pixmap)
    
    def save_image(self):
        """保存当前图像"""
        if self.current_image is not None:
            filename, _ = QFileDialog.getSaveFileName(
                self, "保存图像", "", "JPEG Files (*.jpg);;PNG Files (*.png);;BMP Files (*.bmp)"
            )
            if filename:
                cv2.imwrite(filename, self.current_image)
                self.status_label.setText(f"图像已保存: {filename}")
    
    def closeEvent(self, event):
        """关闭事件"""
        self.stop_camera()
        event.accept()

def main():
    app = QApplication(sys.argv)
    window = SimpleCameraDemo()
    window.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main() 